package charts.series.bars; 
	
import flash.filters.DropShadowFilter;
import flash.geom.Matrix;

class CylinderOutline extends ElementBase {
	
	
	
	public function new( index:Float, style:Dynamic, group:Float ) {
		
		super(index, style, style.colour, style.tip, style.alpha, group);
		
		var dropShadow:DropShadowFilter = new flash.filters.DropShadowFilter();
		dropShadow.blurX = 5;
		dropShadow.blurY = 5;
		dropShadow.distance = 3;
		dropShadow.angle = 45;
		dropShadow.quality = 2;
		dropShadow.alpha = 0.4;
		// apply shadow filter
		this.filters = [dropShadow];
	}
	
	public override function resize( sc:ScreenCoordsBase ):Void {
		
		this.graphics.clear();
		var h:Dynamic = this.resize_helper( cast( sc, ScreenCoords) );
		
		this.bg( h.width, h.height, h.upside_down );
		this.glass( h.width, h.height, h.upside_down );
	}
	
	function bg( w:Float, h:Float, upside_down:Bool ):Void {
	
		var rad:Int = w/3;
		if ( rad > ( w / 2 ) )
		rad = w / 2;
		
		this.graphics.lineStyle(0, 0, 0);// this.outline_colour, 100);
		
		var bgcolors:Array<Dynamic> = GetColours(this.colour);
		var bgalphas:Array<Dynamic> = [1, 1];
		var bgratios:Array<Dynamic> = [0, 255];
		var bgmatrix:Matrix = new Matrix();
		var xRadius:Float;
		var yRadius:Float;
		var x:Float;
		var y:Float;
		
		bgmatrix.createGradientBox(w, h, (180 / 180) * Math.PI );
		this.graphics.beginGradientFill('linear' /*GradientType.Linear*/, bgcolors, bgalphas, bgratios, bgmatrix, 'pad'/*SpreadMethod.PAD*/ );
		
		/* draw bottom half ellipse */
		x = w/2;
		y = h;
		xRadius = w / 2;
		yRadius = rad / 2;
		halfEllipse(x, y, xRadius, yRadius, 100, false);
			
		/* draw connecting rectangle */
		this.graphics.beginGradientFill('linear' /*GradientType.Linear*/, bgcolors, bgalphas, bgratios, bgmatrix, 'pad'/*SpreadMethod.PAD*/ );
		this.graphics.moveTo(0, 0);
		this.graphics.lineTo(0, h);
		this.graphics.lineTo(w, h);
		this.graphics.lineTo(w, 0);   
			
		/* draw top ellipse */
		//this.graphics.beginFill(this.colour, 1);
		this.graphics.beginGradientFill('linear' /*GradientType.Linear*/, bgcolors, bgalphas, bgratios, bgmatrix, 'pad'/*SpreadMethod.PAD*/ );
		x = w / 2;
		y = 0;
		xRadius = w / 2;
		yRadius = rad / 2;
		Ellipse(x, y, xRadius, yRadius, 100);
		
		this.graphics.endFill();
	}
	
	function glass( w:Float, h:Float, upside_down:Bool ): Void {
	
	/* if this section is commented out, the white shine overlay will not be drawn */
	
	this.graphics.lineStyle(0, 0, 0);
	//set gradient fill
	var bgcolors:Array<Dynamic> = GetColours(this.colour);
	var bgalphas:Array<Dynamic> = [1, 1];
	var bgratios:Array<Dynamic> = [0, 255];
	var bgmatrix:Matrix = new Matrix();
	var colors:Array<Dynamic> = [0xFFFFFF, 0xFFFFFF];
	var alphas:Array<Dynamic> = [0, 0.5];
	var ratios:Array<Dynamic> = [150,255];         
	var xRadius:Float;
	var yRadius:Float;
	var x:Float;
	var y:Float;
	var matrix:Matrix = new Matrix();
	matrix.createGradientBox(width, height, (180 / 180) * Math.PI );
	this.graphics.beginGradientFill('linear' /*GradientType.Linear*/, colors, alphas, ratios, matrix, 'pad'/*SpreadMethod.PAD*/ );
	var rad:Int = w / 3;
	
	/* draw bottom half ellipse shine */
	x = w/2;
	y = h;
	xRadius = w / 2 - (0.025*w);
	yRadius = rad / 2 - (0.025*w);
	halfEllipse(x, y, xRadius, yRadius, 100, false);
	
	/*draw connecting rectangle shine */
	this.graphics.moveTo(0 + (0.025*w), 0 + (0.025*w));
	this.graphics.lineTo(0 + (0.025*w), h);
	this.graphics.lineTo(w - (0.025*w), h);
	this.graphics.lineTo(w - (0.025*w), 0 + (0.025*w));   
			
		
	/* redraw top ellipse (to overwrite connecting rectangle shine overlap)*/
	//this.graphics.beginFill(this.colour, 1);
	this.graphics.beginGradientFill('linear' /*GradientType.Linear*/, bgcolors, bgalphas, bgratios, bgmatrix, 'pad'/*SpreadMethod.PAD*/ );
	x = w / 2;
	y = 0;
	xRadius = w / 2;
	yRadius = rad / 2;
	Ellipse(x, y, xRadius, yRadius, 100);   
	
	/* draw top ellipse shine */
	this.graphics.beginGradientFill('linear' /*GradientType.Linear*/, colors, alphas, [25,255], matrix, 'pad'/*SpreadMethod.PAD*/ );
	x = w / 2;
	y = 0;
	xRadius = w / 2  - (0.025*w);
	yRadius = rad / 2  - (0.025*w);
	Ellipse(x, y, xRadius, yRadius, 100);
		
	this.graphics.endFill();
	}
	
	/* function to process colors */
	/* returns a base color and a highlight color for the gradients based on the color passed in */
	public static function GetColours( col:Float ):Array<Dynamic> {
	var rgb:Int = col; /* decimal value for color */
	var red:Int = (rgb & 16711680) >> 16; /* extacts the red channel */
	var green:Int = (rgb & 65280) >> 8; /* extacts the green channel */
	var blue:Int = rgb & 255; /* extacts the blue channel */
	var shift:Int = 2; /* shift factor */
	var basecolor:Int = col; /* base color to be returned */
	var highlight:Int = col; /* highlight color to be returned */
	var bgred:Int = (rgb & 16711680) >> 16; /* red channel for highlight */
	var bggreen:Int = (rgb & 65280) >> 8; /* green channel for highlight */
	var bgblue:Int = rgb & 255; /* blue channel for highlight */
	var hired:Int = (rgb & 16711680) >> 16; /* red channel for highlight */
	var higreen:Int = (rgb & 65280) >> 8; /* green channel for highlight */
	var hiblue:Int = rgb & 255; /* blue channel for highlight */
	
	/* set base color components based on ability to shift lighter */   
	if (red + red / shift > 255 || green + green / shift > 255 || blue + blue / shift > 255)
	{
	bgred = red - red / shift;
	bggreen = green - green / shift;
	bgblue = blue - blue / shift;
	}            
	
	/* set highlight components based on base colors */   
	hired = bgred + red / shift;
	hiblue = bgblue + blue / shift;
	higreen = bggreen + green / shift;
	
	/* reconstruct base and highlight */
	basecolor = bgred << 16 | bggreen << 8 | bgblue;
	highlight = hired << 16 | higreen << 8 | hiblue;
		
	/* return base and highlight */
	return [highlight, basecolor];
	}
	
	/* ellipse cos helper function */
	public static function magicTrigFunctionX (pointRatio:Float):Float{
	return Math.cos(pointRatio*2*Math.PI);
	}
	
	/* ellipse sin helper function */
	public static function magicTrigFunctionY (pointRatio:Float):Float{
	return Math.sin(pointRatio*2*Math.PI);
	}
	
	/* ellipse function */
	/* draws an ellipse from passed center coordinates, x and y radii, and number of sides */
	public function Ellipse(centerX:Float, centerY:Float, xRadius:Float, yRadius:Float, sides:Float):Float{
	
	/* move to first point on ellipse */
	this.graphics.moveTo(centerX + xRadius,  centerY);
	
	/* loop through sides and draw curves */
	var i:Int=0;
	while (i<=sides){
	var pointRatio:Int = i/sides;
	var xSteps:Int = magicTrigFunctionX(pointRatio);
	var ySteps:Int = magicTrigFunctionY(pointRatio);
	var pointX:Int = centerX + xSteps * xRadius;
	var pointY:Int = centerY + ySteps * yRadius;
	this.graphics.lineTo(pointX, pointY);
	i++;
	}
	
	/* return 1 */
	return 1;
	}
	
	/* half ellipse function */
	/* draws half of an ellipse from passed center coordinates, x and y radii, number of sides , and top/bottom */
	public function halfEllipse(centerX:Float, centerY:Float, xRadius:Float, yRadius:Float, sides:Float, top:Bool):Float{
	
	var loopStart:Float;
	var loopEnd:Float;
	
	if (top == true)
	{
	loopStart = sides / 2;
	loopEnd = sides;
	}
	else
	{
	loopStart = 0;
	loopEnd = sides / 2;            
	}
	
	/* move to first point on ellipse */
	this.graphics.moveTo(centerX + xRadius,  centerY);
	
	/* loop through sides and draw curves */
	var i:Int=loopStart;
	while (i<=loopEnd){
	var pointRatio:Int = i/sides;
	var xSteps:Int = magicTrigFunctionX(pointRatio);
	var ySteps:Int = magicTrigFunctionY(pointRatio);
	var pointX:Int = centerX + xSteps * xRadius;
	var pointY:Int = centerY + ySteps * yRadius;
	this.graphics.lineTo(pointX, pointY);
	i++;
	}
	
	/* return 1 */
	return 1;
	}
	
}
